package com.bbz.core.concurrency.work1;

/**
 * 线程sleep和wait Demo
 * 
 * sleep() VS wait() 两者主要的区别： sleep()方法是Thread的静态方法，而wait是Object实例方法
 * wait()方法必须要在同步方法或者同步块中调用，也就是必须已经获得对象锁。
 * 而sleep()方法没有这个限制可以在任何地方种使用。另外，wait()方法会释放占有的对象锁，
 * 使得该线程进入等待池中，等待下一次获取资源。而sleep()方法只是会让出CPU并不会释放掉对象锁；
 * sleep()方法在休眠时间达到后如果再次获得CPU时间片就会继续执行，
 * 而wait()方法必须等待Object.notift/Object.notifyAll通知后，才会离开等待池，并且再次获得CPU时间片才会继续执行。
 *
 * @author binbin.a.zhang
 *
 */
public class SleepWaitDemo {
	private void sleep() {
		Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					System.out.println("Sleep:1000");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		thread.start();
	}

	private String flag[] = { "true" };

	class NotifyThread extends Thread {
		public NotifyThread(String name) {
			super(name);
		}

		public void run() {
			try {
				sleep(3000);// 推迟3秒钟通知
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			synchronized (flag) {
				flag[0] = "false";
				flag.notifyAll();
			}
		}
	};

	class WaitThread extends Thread {
		public WaitThread(String name) {
			super(name);
		}

		public void run() {
			synchronized (flag) {
				while (flag[0] != "false") {
					System.out.println(getName() + " begin waiting!");
					long waitTime = System.currentTimeMillis();

					try {
						flag.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					waitTime = System.currentTimeMillis() - waitTime;
					System.out.println("wait time :" + waitTime);
				}
				System.out.println(getName() + " end waiting!");
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		System.out.println("Main Thread Run!");
		SleepWaitDemo test = new SleepWaitDemo();
		NotifyThread notifyThread = test.new NotifyThread("notify01");
		WaitThread waitThread01 = test.new WaitThread("waiter01");
		WaitThread waitThread02 = test.new WaitThread("waiter02");
		WaitThread waitThread03 = test.new WaitThread("waiter03");
		notifyThread.start();
		waitThread01.start();
		waitThread02.start();
		waitThread03.start();
	}

}
